package com.dao.aop;

import java.util.Date;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.common.DateUtils;
import com.common.StringUtils;
import com.common.model.ActionEnum;
import com.common.model.Global;
import com.common.model.UserTypeEnum;
import com.common.spring.SpringMvcUtils;
import com.common.utils.BeanUtil;
import com.dao.sys.LogDao;
import com.model.supply.SupplyUserModel;
import com.model.sys.LogModel;
import com.model.sys.SysUser;

@Component
@Aspect
public class DaoAspect {

	@Autowired
	LogDao logDao;

	private final static Logger logger = LoggerFactory.getLogger(DaoAspect.class);

	private static final String ID = "id";
	private static final String STATUS = "status";
	private static final String CREATE_BY = "createId";
	private static final String CREATE_BY_NAME = "createName";
	private static final String CREATE_TIME = "createTime";
	private static final String UPDATE_BY = "updateId";
	private static final String UPDATE_BY_NAME = "updateName";
	private static final String UPDATE_TIME = "updateTime";
	private static final String DEL_FLAG = "delFlag";
	private static final String DEPT_ID = "deptId";

	@Pointcut("execution(* com.dao..*.update*(..))")
	public void daoUpdate() {
	}

	@Pointcut("execution(* com.dao..*.insert*(..))")
	public void daoCreate() {
	}

	@Pointcut("execution(* com.dao..*.delete*(..))")
	public void daoDelete() {
	}

	@Around("daoDelete()")
	public Object doAroundDelete(ProceedingJoinPoint point) throws Throwable {
		Object[] objects = point.getArgs();
		if (objects != null && objects.length > 0) {
			for (Object arg : objects) {
				logger.debug(arg.toString());
				LogModel logModel = new LogModel();
				logModel.setLogId(UUID.randomUUID().toString());
				logModel.setLogContent(arg.toString());
				logModel.setLogAction(ActionEnum.del.getName());
				logModel.setCreateTime(DateUtils.getCurrentTime());
				Object userType = SpringMvcUtils.getUserType();
				if (userType == null) {
					logDao.insert(logModel);
					return point.proceed();
				}
				if (userType.toString().equals(UserTypeEnum.XYUser.getValue())) {
					SysUser sysUser = SpringMvcUtils.getSysUser();
					if (sysUser == null) {
						return point.proceed();
					}
					logModel.setCreateId(sysUser.getUserid());
				} else if (userType.toString().equals(UserTypeEnum.SupplyUser.getValue())) {
					SupplyUserModel sysUser = SpringMvcUtils.getSupplyUser();
					if (sysUser == null) {
						return point.proceed();
					}
					logModel.setCreateId(sysUser.getCreateId());
				}
				logDao.insert(logModel);
			}
		}

		Object object = point.proceed();
		return object;
	}

	@Around("daoUpdate()")
	public Object doAroundUpdate(ProceedingJoinPoint point) throws Throwable {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		if (attributes == null) {
			return point.proceed();
		}
		HttpServletRequest request = attributes.getRequest();
		String userId = "";
		String userName = "";
		Object userType = SpringMvcUtils.getUserType();
		if (userType == null) {
			return point.proceed();
		}
		if (userType.toString().equals(UserTypeEnum.XYUser.getValue())) {
			SysUser sysUser = (SysUser) request.getSession().getAttribute("sysUser");
			if (sysUser == null) {
				return point.proceed();
			}
			userId = sysUser.getUserid();
			userName = sysUser.getUsername();
		} else if (userType.toString().equals(UserTypeEnum.SupplyUser.getValue())) {
			SupplyUserModel sysUser = (SupplyUserModel) request.getSession().getAttribute("supplyUserModel");
			if (sysUser == null) {
				return point.proceed();
			}
			userId = sysUser.getUserId();
			userName = sysUser.getUserName();
		}
		String date = DateUtils.getCurrentTime();
		if (userId != null) {
			Object[] objects = point.getArgs();
			if (objects != null && objects.length > 0) {
				for (Object arg : objects) {
					if (isProperty(arg, UPDATE_BY)) {
						BeanUtils.setProperty(arg, UPDATE_BY, userId);
					}
					if (isProperty(arg, UPDATE_BY_NAME)) {
						BeanUtils.setProperty(arg, UPDATE_BY_NAME, userName);
					}
					if (isProperty(arg, UPDATE_TIME)) {
						BeanUtils.setProperty(arg, UPDATE_TIME, date);
					}
				}
			}
		}
		Object object = point.proceed();
		return object;

	}

	@Around("daoCreate()")
	public Object doAroundCreate(ProceedingJoinPoint point) throws Throwable {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		if (attributes == null) {
			return point.proceed();
		}
		HttpServletRequest request = attributes.getRequest();
		Object[] objects = point.getArgs();
		if (objects != null && objects.length > 0) {
			for (Object arg : objects) {
				String userId = "";
				String userName = "";
				String deptIdString = "";
				Object userType = SpringMvcUtils.getUserType();
				if (userType == null) {
					return point.proceed();
				}
				if (userType.toString().equals(UserTypeEnum.XYUser.getValue())) {
					SysUser sysUser = (SysUser) request.getSession().getAttribute("sysUser");
					if (sysUser == null) {
						return point.proceed();
					}
					userId = sysUser.getUserid();
					userName = sysUser.getUsername();
					deptIdString = sysUser.getDeptid();
				} else if (userType.toString().equals(UserTypeEnum.SupplyUser.getValue())) {
					SupplyUserModel sysUser = (SupplyUserModel) request.getSession().getAttribute("supplyUserModel");
					if (sysUser == null) {
						return point.proceed();
					}
					userId = sysUser.getUserId();
					userName = sysUser.getUserName();
				}
				String date = DateUtils.getCurrentTime();
				if (userId != null) {
					if (isProperty(arg, CREATE_BY) && !StringUtils.isNotNull(BeanUtils.getProperty(arg, CREATE_BY))) {
						BeanUtils.setProperty(arg, CREATE_BY, userId);
					}
					if (isProperty(arg, UPDATE_BY)) {
						BeanUtils.setProperty(arg, UPDATE_BY, userId);
					}
				}

				if (isProperty(arg, DEPT_ID) && !StringUtils.isNotNull(BeanUtils.getProperty(arg, DEPT_ID))) {
					BeanUtils.setProperty(arg, DEPT_ID, deptIdString);
				}

				if (userName != null) {
					if (isProperty(arg, CREATE_BY_NAME)
							&& !StringUtils.isNotNull(BeanUtils.getProperty(arg, CREATE_BY_NAME))) {
						BeanUtils.setProperty(arg, CREATE_BY_NAME, userName);
					}
					if (isProperty(arg, UPDATE_BY_NAME)) {
						BeanUtils.setProperty(arg, UPDATE_BY_NAME, userName);
					}
				}

				if (isProperty(arg, CREATE_TIME) && !StringUtils.isNotNull(BeanUtils.getProperty(arg, CREATE_TIME))) {
					BeanUtils.setProperty(arg, CREATE_TIME, date);
				}

				if (isProperty(arg, UPDATE_TIME)) {
					BeanUtils.setProperty(arg, UPDATE_TIME, date);
				}

				if (isProperty(arg, ID) && !StringUtils.isNotNull(BeanUtils.getProperty(arg, ID))) {
					BeanUtils.setProperty(arg, ID, UUID.randomUUID().toString());
				}

				if (isProperty(arg, STATUS) && !StringUtils.isNotNull(BeanUtils.getProperty(arg, STATUS))) {
					BeanUtils.setProperty(arg, STATUS, Global.NO);
				}

				if (isProperty(arg, DEL_FLAG) && !StringUtils.isNotNull(BeanUtils.getProperty(arg, DEL_FLAG))) {
					BeanUtils.setProperty(arg, DEL_FLAG, Global.NO);
				}
			}
		}
		Object object = point.proceed();
		return object;
	}

	public static boolean isProperty(Object bean, String field) {
		return com.common.utils.BeanUtil.isProperty(bean, field);
	}
}
